package com.app.shop.config.security;

import com.app.shop.config.filter.JWTAuthenticationFilter;
import com.app.shop.config.filter.JWTLoginFilter;
import com.app.shop.config.filter.XFilterInvocationSecurityMetadataSource;
import com.app.shop.service.system.SecurityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.csrf.CsrfFilter;
import org.springframework.security.web.header.Header;
import org.springframework.security.web.header.writers.StaticHeadersWriter;
import org.springframework.web.filter.CharacterEncodingFilter;

import java.util.Arrays;


/**
 * SunPasswordEncoder  Security访问权限控制类
 *
 * @author chenliwei
 * @version 1.0 2017-11-5
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {



    @Autowired(required = false)
    private SecurityService securityService;
    @Autowired
    XFilterInvocationSecurityMetadataSource xFilterInvocationSecurityMetadataSource;
    @Autowired
    XAccessDecisionManager xAccessDecisionManager;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new XSecurityPasswordEncoder();
    }

    /**
     * Security请求过滤器
     * @author chenliwei
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        //配置编码方式
        CharacterEncodingFilter characterEncodingFilter=new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceEncoding(true);
        http.addFilterBefore(characterEncodingFilter, CsrfFilter.class);
        //添加自动401和403返回
        http.exceptionHandling().authenticationEntryPoint(new EntryPointUnauthorizedHandler())
                .accessDeniedHandler(new RestAccessDeniedHandler());
        //禁用csrf      http.csrf().disable()
        http.csrf().disable()
                //停止使用session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                //禁用form登录.formLogin().disable()
                .and()
                //cors支持跨域
                .cors()
                //添加header设置，支持跨域和ajax请求
                .and().headers().addHeaderWriter(new StaticHeadersWriter(Arrays.asList(
                new Header("Access-control-Allow-Origin","*"),
                new Header("Access-Control-Expose-Headers","Authorization"))));
        //http.headers().frameOptions().disable();
        // 禁用缓存
        //httpSecurity.headers().cacheControl();
        http.authorizeRequests()
                //登陆URL权限控制器
//                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
//                    @Override
//                    public <O extends FilterSecurityInterceptor> O postProcess(O o) {
//                        //全量权限控制器
//                        o.setSecurityMetadataSource(xFilterInvocationSecurityMetadataSource);
//                        //当前用户权限控制器
//                        o.setAccessDecisionManager(xAccessDecisionManager);
//                        return o;
//                    }
//                })
                .antMatchers("/system/verificationCode","/login", "/static/**", "/api/**","/file/**").permitAll()
                .anyRequest().authenticated() //其他的路径都是登录后即可访问
                .and()
                .addFilter(new JWTLoginFilter(authenticationManager()))
                .addFilter(new JWTAuthenticationFilter(authenticationManager()))
                //使用默认的logoutFilter
                .logout()
//              .logoutUrl("/logout")   //默认就是"/logout"
//                .addLogoutHandler(tokenClearLogoutHandler())  //logout时清除token
//                .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler()) //logout成功后返回200
                .and().httpBasic();


    }


    @Bean(name = "frontAuthenticationProvider")
    public XAuthenticationProvider frontAuthenticationProvider() {
        XAuthenticationProvider daoAuthenticationProvider = new XAuthenticationProvider();
        daoAuthenticationProvider.setUserDetailsService(securityService);
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        //设置前端抛出用户名称不存在错误
        daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
        return daoAuthenticationProvider;
    }



    /**
     * @param web 配置静态文件过滤
     * @throws Exception
     * @author chenliwei
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        //静态资源被拦截放行
        web.ignoring().antMatchers("/WEB-INF/static/**");
    }





}


